package com.franz.noteapp.compose.showNotes

import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.franz.noteapp.bean.NoteBean
import com.franz.noteapp.bean.NoteOrder
import com.franz.noteapp.bean.NoteType
import com.franz.noteapp.useCase.NoteUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class NotesViewModel @Inject constructor(private val noteUseCase: NoteUseCase):ViewModel(){

    /**
     * 笔记内容状态管理
     * 所有笔记内容、排序方式、是否显示排序组件*/
    private val _state = mutableStateOf(NotesState())
    val state: State<NotesState> = _state

    /**
     * 存储最近被删除的笔记*/
    private var recentlyDeleteNote:NoteBean? = null

    private var getNotesJob: Job? = null

    /**
     * 默认以时间降序进行排序*/
    init {
        getNotes(NoteType.Date(NoteOrder.Descending))
    }


    fun onEvent(event: NotesEvent){
        when(event){
            /**
             * 对笔记内容进行排序，如果当前排序类型和方式一样则不进行任何操作
             * 否则重新根据排序方式进行排序*/
            is NotesEvent.Type ->{
                if (state.value.noteType == event.noteType &&
                    state.value.noteType.noteOrder == event.noteType.noteOrder){
                    return
                }
                getNotes(event.noteType)
            }
            /**
             * 删除笔记操作，然后将最近被删除的笔记赋值给一个临时变量进行暂时存储*/
            is NotesEvent.Delete ->{
                viewModelScope.launch {
                    noteUseCase.deleteNote(event.bean)
                    recentlyDeleteNote = event.bean
                }
            }
            /**
             * 撤回最近被删除的笔记，从临时变量中*/
            is NotesEvent.RestoreNote ->{
               viewModelScope.launch {
                   noteUseCase.insertNote(recentlyDeleteNote ?: return@launch)
                   recentlyDeleteNote = null
               }
            }
            /**
             * 显示/隐藏排序组件*/
            is NotesEvent.ToggleOrderSection ->{
                _state.value = state.value.copy(
                    isOrderSectionVisible = !state.value.isOrderSectionVisible
                )
            }
        }
    }

    /**
     * 这是因为 SQLite 数据库的内容更新通知功能是以表 (Table) 数据为单位，而不是以行 (Row) 数据为单位，因此只要是表中的数据有更新，
     * 它就触发内容更新通知。Room 不知道表中有更新的数据是哪一个，因此它会重新触发 DAO 中定义的 query 操作。
     * 您可以使用 Flow 的操作符，比如 distinctUntilChanged 来确保只有在当您关心的数据有更新时才会收到通知
    */


    /**
     * 重新对笔记内容进行排序
     * Room数据库其中的Dao的实现类，查询表中所有数据用的是Flow<List<xxxBean>>进行返回
     * 一旦表中任何一行发生变化，Room数据库就会通过Dao类的query方法重新获取表中所有数据，然后派发给Flow
     * 这就是为什么通过dao的实现类进行删除或者插入操作，UI界面会发生对应改变*/
    private fun getNotes(type: NoteType){
        getNotesJob?.cancel()
        getNotesJob = noteUseCase.getNotes(type).onEach {
            notes->
            /*room表中数据发生变化，此处会重新被执行*/
            _state.value = state.value.copy(
                notes = notes,
                noteType = type
            )
        }.launchIn(viewModelScope)
    }

}